#ifndef __COMMONFUNC_H__
#define __COMMONFUNC_H__

#ifdef COMMONFUNC_EXPORTS
#define COMMONFUNC_API __declspec(dllexport)
#else
#define COMMONFUNC_API __declspec(dllimport)
#endif

#include <stdint.h>

#ifndef MIN
#define MIN(a, b) ((a)<(b) ? (a):(b))
#endif
#ifndef MAX
#define MAX(a, b) ((a)>(b) ? (a):(b))
#endif
#ifndef ROUND
#define ROUND(a) (((a) >= (0.0f)) ? (int((a)+0.5f)):(int((a)-0.5f)))
#endif
#ifndef VALRANGE
#define VALRANGE(val, minV, maxV) MAX(MIN((val), (maxV)), (minV))
#endif
#ifndef IS_IN_RANGE
#define IS_IN_RANGE(val, minV, maxV) ((val) >= (minV) && (val) < (maxV))
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
#endif

#define GET_BITS(field,offset,mask)         ( ( (field) >> (offset) ) & (mask) )
#define GET_BIT(field,offset)               ( GET_BITS(field,offset,0x1) )

extern "C" 
{
COMMONFUNC_API const char* commonfunc_version(void);
COMMONFUNC_API int commonfunc_version_number(void);

COMMONFUNC_API void KdPrintA(const char *format, ...);
COMMONFUNC_API void KdPrintW(const wchar_t *format, ...);

#define printk KdPrintA

COMMONFUNC_API int AnsiToUnicode(const char *in, int in_len, wchar_t* out, int max_out_len);
COMMONFUNC_API int UnicodeToAnsi(const wchar_t *in, int in_len, char* out, int max_out_len);

COMMONFUNC_API void PrintDebugArray(const void *array, int len);
COMMONFUNC_API int Array2String(const void *array, int len, char *destStr, int maxLen, 
                                int num_in_each_line = 16, 
                                char *split=" ", char *addon = "\n");

COMMONFUNC_API uint32_t CheckSum(const void *in, int len);
COMMONFUNC_API void Reverse(void *in, int len);

/* Attention: split will change the input str */
COMMONFUNC_API int split(char *str, char **arr, const char *del);
COMMONFUNC_API int split_int(char *str, const char *del, int val[], int max_num);
COMMONFUNC_API int split_double(char *str, const char *del, double val[], int max_num);

COMMONFUNC_API uint32_t get_le_val(const uint8_t *p, int bytes);
COMMONFUNC_API uint32_t get_be_val(const uint8_t *p, int bytes);
COMMONFUNC_API void put_le_val(uint32_t val, uint8_t *p, int bytes);
COMMONFUNC_API void put_be_val(uint32_t val, uint8_t *p, int bytes);

COMMONFUNC_API int compare_float(double x1, double x2);
COMMONFUNC_API double duround(double indata, int precision);

COMMONFUNC_API int file_size(const char *file);
COMMONFUNC_API int file_write(const char *file, int addr, const void *data, int len);
COMMONFUNC_API int file_read(const char *file, int addr, void *data, int len);

COMMONFUNC_API 
void get_build_time(const char *date, const char *time, char *out, int max_count);

COMMONFUNC_API unsigned long
maketime(const unsigned int, const unsigned int, const unsigned int, 
         const unsigned int, const unsigned int, const unsigned int);

#define MD5DIGESTLEN 16
COMMONFUNC_API 
int get_hash(const void *in, int len, uint8_t *out);
}
#endif